(define-module (fiasco fixer)
  #:use-module (fiasco finder)
  #:use-module (guix base32)
  #:use-module (guix upstream)

  #:export (fix-packages-hash))

;;; Commentary:
;;;
;;; Repair the packages whose hash can be safely updated, as found by
;;; the finder script. This should be run from a checkout of the Guix
;;; source tree, e.g. as "./pre-inst-guix guile ~/src/guile-hacks/fiasco/run.scm

(define (result-needs-checking? result)
  (and (not (result-hash-ok? result))
       (not (result-safe-to-update? result))))

(define* (fix-packages-hash #:optional (file (results-file)))
  "Correct the packages whose hash can be safely updated, based on
data in FILE."
  (let* ((results (results-file->results file))
	 (results-to-check (filter result-needs-checking? results))
	 (actionable-results (filter result-safe-to-update? results)))

    (define (update-package-hash result)
      (when (not (null? (result->package result)))
	(let* ((package (result->package result))
	       (name (result-package-name result))
	       (version (result-package-version result))
	       (old-hash (result-guix-hash result))
	       (new-hash (result-upstream-hash result))
	       (new-hash-bv (nix-base32-string->bytevector new-hash)))
	  (format #t "~a: updating hash from ~s to ~s..." name old-hash new-hash)
	  (if (update-package-source package version new-hash-bv)
	      (format #t "   success~%")
	      (format #t "   failed~%")))))

    (format #t "The following packages require manual verification:~%")
    (for-each (lambda (r)
		(format #t "~a version ~a~%"
			(result-package-name r)
			(result-package-version r)))
	      results-to-check)
    (display "\n")

    (format #t "Attempting to repair the hashes of ~a packages...~%"
	    (length actionable-results))

    (for-each update-package-hash actionable-results)))
